<template>
  <BubbleContainer :should-show="handleShouldShow">
    <!-- 文本选择菜单 -->
    <template v-if="menuType === 'text'">
      <slot name="text">
        <TextBubbleMenu />
      </slot>
    </template>

    <!-- 链接菜单 -->
    <template v-else-if="menuType === 'link'">
      <slot name="link">
        <!-- 链接菜单占位，后续可扩展 -->
        <TextBubbleMenu />
      </slot>
    </template>

    <!-- 图片菜单 -->
    <template v-else-if="menuType === 'image'">
      <slot name="image">
        <!-- 图片菜单占位，后续可扩展 -->
        <div class="bubble-menu-placeholder">图片菜单</div>
      </slot>
    </template>

    <!-- 表格菜单 -->
    <template v-else-if="menuType === 'table'">
      <slot name="table">
        <!-- 表格菜单占位，后续可扩展 -->
        <div class="bubble-menu-placeholder">表格菜单</div>
      </slot>
    </template>

    <!-- 标题菜单 -->
    <template v-else-if="menuType === 'heading'">
      <slot name="heading">
        <!-- 标题菜单占位，后续可扩展 -->
        <TextBubbleMenu />
      </slot>
    </template>

    <!-- 批注菜单 -->
    <template v-else-if="menuType === 'comment'">
      <slot name="comment">
        <CommentBubbleMenuWrapper />
      </slot>
    </template>
  </BubbleContainer>
</template>

<script setup lang="ts">
import { ref } from "vue";
import type { Editor } from "@tiptap/vue-3";
import BubbleContainer from "./BubbleContainer.vue";
import TextBubbleMenu from "./text/index.vue";
import CommentBubbleMenuWrapper from "./comment/index.vue";

defineOptions({
  name: "BubbleMenu",
});

type MenuType =
  | "text"
  | "link"
  | "image"
  | "table"
  | "heading"
  | "comment"
  | "default"
  | null;

// 当前菜单类型
const menuType = ref<MenuType>(null);

/**
 * 检测菜单类型
 */
const detectMenuType = (currentEditor: Editor): MenuType => {
  if (!currentEditor) return null;

  const { selection } = currentEditor.state;
  const { from, to } = selection;

  // 如果没有选中内容，不显示菜单
  if (from === to) return null;

  // 检查选择是否在分页符节点内，如果是则不显示菜单
  let hasPageBreak = false;
  try {
    currentEditor.state.doc.nodesBetween(from, to, (node) => {
      if (node.type.name === "pageBreak") {
        hasPageBreak = true;
        return false; // 停止遍历
      }
    });
  } catch (e) {
    // 忽略错误，继续检查
  }

  // 如果选择包含分页符节点，不显示菜单
  if (hasPageBreak) {
    return null;
  }

  // 检测是否为链接（优先级最高）
  if (currentEditor.isActive("link")) {
    return "link";
  }

  // 检测是否为图片
  if (currentEditor.isActive("image")) {
    return "image";
  }

  // 检测是否为表格
  if (currentEditor.isActive("table")) {
    return "table";
  }

  // 检测是否为批注（优先级高于标题）
  if (currentEditor.isActive("comment")) {
    return "comment";
  }

  // 检测是否为标题
  if (
    currentEditor.isActive("heading", { level: 1 }) ||
    currentEditor.isActive("heading", { level: 2 }) ||
    currentEditor.isActive("heading", { level: 3 }) ||
    currentEditor.isActive("heading", { level: 4 }) ||
    currentEditor.isActive("heading", { level: 5 }) ||
    currentEditor.isActive("heading", { level: 6 })
  ) {
    return "heading";
  }

  // 默认显示文本菜单
  return "text";
};

/**
 * BubbleMenuContainer 的 shouldShow 回调
 */
const handleShouldShow = (props: {
  editor: Editor;
  element: HTMLElement;
  view: any;
  state: any;
  oldState?: any;
  from: number;
  to: number;
}) => {
  const { editor: currentEditor, from, to } = props;
  if (!currentEditor) {
    menuType.value = null;
    return false;
  }

  // 如果没有选中内容，不显示菜单
  if (from === to) {
    menuType.value = null;
    return false;
  }

  // 检查选择是否包含分页符节点
  let hasPageBreak = false;
  try {
    currentEditor.state.doc.nodesBetween(from, to, (node) => {
      if (node.type.name === "pageBreak") {
        hasPageBreak = true;
        return false; // 停止遍历
      }
    });
  } catch (e) {
    // 忽略错误，继续检查
  }

  // 如果选择包含分页符节点，不显示菜单
  if (hasPageBreak) {
    menuType.value = null;
    return false;
  }

  const detectedType = detectMenuType(currentEditor);
  menuType.value = detectedType;

  return detectedType !== null;
};
</script>

<style lang="scss" scoped>
.bubble-menu-placeholder {
  padding: 8px 16px;
  font-size: 12px;
  color: var(--editor-text-color-light);
}
</style>
